C# 基本语法学习
参考资料 菜鸟教程 C# 基本语法
配置插件查看源码
用 IDEA 写 Java写习惯了,平时写代码时总是习惯性的查看源码,但是到了 VS2019 这里无法直接看到源码,只能看到函数的定义,这点实在是有点不爽,这里来配置一下环境,使之能直接查看源码
如果使用的是 Resharper 这样设置就行了
隐式转换
在学习 Unity 时看到这个 static implicit operator
有点好奇它是什么,实际上它就是一个隐式转换用的语法
使用如下
public struct Vector2 {
// Vector3 转换成 Vector2
public static implicit operator Vector2(Vector3 v){
return new Vector2(v.x,v.y);
}
// Vector2 转换成 Vector3
public static implicit operator Vector3(Vector2 v){
return new Vector3(v.x,v.y,0);
}
}
所以这个就是 RaycastHit2D 转换成 bool
public static implicit operator bool(RaycastHit2D hit);
C# 一些重要的功能
- 布尔条件(Boolean Conditions)
- 自动垃圾回收(Automatic Garbage Collection)
- 标准库(Standard Library)
- 组件版本(Assembly Versioning)
- 属性(Properties)和事件(Events)
- 委托(Delegates)和事件管理(Events Management)
- 易于使用的泛型(Generics)
- 索引器(Indexers)
- 条件编译(Conditional Compilation)
- 简单的多线程(Multithreading)
- LINQ 和 Lambda 表达式
- 集成 Windows
字符串(String)类型
字符串(String)类型 允许您给变量分配任何字符串值。字符串(String)类型是 System.String
类的别名。它是从对象(Object)类型派生的。字符串(String)类型的值可以通过两种形式进行分配:引号和 @
引号。
例如:
String str = "example.com";
一个 @
引号字符串:
@"example.com";
C# string 字符串的前面可以加 @
(称作"逐字字符串")将转义字符(\
)当作普通字符对待,比如:
string str = @"C:\Windows";
等价于:
string str = "C:\\Windows";
@
字符串中可以任意换行,换行符及缩进空格都计算在字符串长度之内。
string str = @"<script type=""text/javascript"">
<!--
-->
</script>";
指针类型(Pointer types)
指针类型变量存储另一种类型的内存地址。C#
中的指针与 C 或 C++ 中的指针有相同的功能。
声明指针类型的语法:
type* identifier;
例如:
char* cptr;
int* iptr;
C# 结构体(Struct)
在 C# 中,结构体是值类型数据结构。
它使得一个单一变量可以存储各种数据类型的相关数据。
struct
关键字用于创建结构体。
struct Books
{
public string title;
public string author;
public string subject;
public int book_id;
};
在 C# 中的结构与传统的 C 或 C++ 中的结构不同。C# 中的结构有以下特点:
- 结构可带有方法、字段、索引、属性、运算符方法和事件。
- 结构可定义构造函数,但不能定义析构函数。但是,不能为结构定义无参构造函数。无参构造函数(默认)是自动定义的,且不能被改变。
- 与类不同,结构不能继承其他的结构或类。
- 结构不能作为其他结构或类的基础结构。
- 结构可实现一个或多个接口。
- 结构成员不能指定为
abstract
、virtual
或protected
。 - 当使用
New
操作符创建一个结构对象时,会调用适当的构造函数来创建结构。 - 与类不同,结构可以不使用
New
操作符即可被实例化。 - 如果不使用
New
操作符,只有在所有的字段都被初始化之后,字段才被赋值,对象才被使用。
类 vs 结构
类和结构有以下几个基本的不同点:
- 类是引用类型,结构是值类型(直接在栈上)。
- 结构不支持继承。
- 结构不能声明默认的构造函数。
命名空间
namespace namespace_name
{
// 代码声明
}
使用例
using System;
namespace first_space
{
class namespace_cl
{
public void func()
{
Console.WriteLine("Inside first_space");
}
}
}
namespace second_space
{
class namespace_cl
{
public void func()
{
Console.WriteLine("Inside second_space");
}
}
}
class TestClass
{
static void Main(string[] args)
{
first_space.namespace_cl fc = new first_space.namespace_cl();
second_space.namespace_cl sc = new second_space.namespace_cl();
fc.func();
sc.func();
Console.ReadKey();
}
}
C# 预处理器指令
下表列出了 C# 中可用的预处理器指令:
预处理器指令 | 描述 |
---|---|
#define | 它用于定义一系列成为符号的字符。 |
#undef | 它用于取消定义符号。 |
#if | 它用于测试符号是否为真。 |
#else | 它用于创建复合条件指令,与 #if 一起使用。 |
#elif | 它用于创建复合条件指令。 |
#endif | 指定一个条件指令的结束。 |
#line | 它可以让您修改编译器的行数以及(可选地)输出错误和警告的文件名。 |
#error | 它允许从代码的指定位置生成一个错误。 |
#warning | 它允许从代码的指定位置生成一级警告。 |
#region | 它可以让您在使用 Visual Studio Code Editor 的大纲特性时,指定一个可展开或折叠的代码块。 |
#endregion | 它标识着 #region 块的结束。 |
形参的知识
default 关键字
这里的 default 关键字不是指 switch 语句中的那个
默认构造函数是通过 new 运算符来调用的
int myInt = new int();
// default(T)如下所示:
int myInt = default(int);
// 以上语句同下列语句效果相同:
int myInt = 0;
在 C# 中可以使用 struct 来定义数据,而 struct 都需要设置一个默认值,这个 default 就是用来取得这个默认值
形参后面的问号
因为某些 struct 修饰的对象不能为 null,这个问号就是让这个参数可以为 null
而普通用 class 修饰的对象是可以为空的
命名实参和可选实参
命名实参
例如,通过以函数定义的顺序按位置发送实参,可以调用打印订单详细信息(例如卖家姓名、订单号和产品名称)的函数。
PrintOrderDetails("Gift Shop", 31, "Red Mug");
如果不记得形参的顺序,但却知道其名称,则可以按任意顺序发送实参。
PrintOrderDetails(orderNum: 31, productName: "Red Mug", sellerName: "Gift Shop");
PrintOrderDetails(productName: "Red Mug", sellerName: "Gift Shop", orderNum: 31);
可选实参
就是一些参数可以省略,使用的它的默认值(大大的减少了方法重载)
public void ExampleMethod(int required, string optionalstr = "default string",
int optionalint = 10)
anExample.ExampleMethod(3, optionalint: 4);
C# 中的 Lambda
参考资料 => 运算符(C# 参考)
在 C# 中与 Java一样有 Lambda,但是 C# 中的 Lambda 则是真正的匿名函数,而非 Java的那种匿名类,因此使用方式和 Java 也是有一定的区别
语法是同 Java的一致
member => expression;
使用匿名函数重写 ToString() 方法
public override string ToString() => $"{fname} {lname}".Trim();
它是下面这个代码的缩写
public override string ToString()
{
return $"{fname} {lname}".Trim();
}
匿名函数
先来介绍一下 C# 中的匿名函数,可以看到,实际上就是通过委托来完成的
class Test
{
delegate void TestDelegate(string s);
static void M(string s)
{
Console.WriteLine(s);
}
static void Main(string[] args)
{
// Original delegate syntax required
// initialization with a named method.
TestDelegate testDelA = new TestDelegate(M);
// C# 2.0: A delegate can be initialized with
// inline code, called an "anonymous method." This
// method takes a string as an input parameter.
TestDelegate testDelB = delegate(string s) { Console.WriteLine(s); };
// C# 3.0. A delegate can be initialized with
// a lambda expression. The lambda also takes a string
// as an input parameter (x). The type of x is inferred by the compiler.
TestDelegate testDelC = (x) => { Console.WriteLine(x); };
// Invoke the delegates.
testDelA("Hello. My name is M and I write lines.");
testDelB("That's nothing. I'm anonymous and ");
testDelC("I'm a famous author.");
// Keep console window open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
/* Output:
Hello. My name is M and I write lines.
That's nothing. I'm anonymous and
I'm a famous author.
Press any key to exit.
*/